import re

from rest_framework import serializers
from django_redis import get_redis_connection
from users.models import User

"""
序列化器的功能：
1. 验证数据
2. 数据入库
3. 将模型转换为字典


"""
# serializers.ModelSerializer
#   自动生成字段 （根据fileds来生成字段）

# serializers.Serializer
#（用户名，手机号，密码，短信验证码，确认密码和是否同意协议
# serializer.data
# user --> RegisterUserSerializer
# read_only 只读 只进行序列化操作
# write_only 只是写入，在当前情况下 值用于 反序列化的数据验证操作，
# 进行序列化操作的时候默认忽略此字段
# sms_code,password2,allow 只是使用它来进行 数据的验证 反序列化
class RegisterUserSerializer(serializers.ModelSerializer):

    # 短信验证码
    sms_code=serializers.CharField(required=True,max_length=6,min_length=6,write_only=True)
    # 确认密码
    # None ''
    password2=serializers.CharField(required=True,allow_null=False,allow_blank=False,write_only=True)
    # 是否同意协议
    allow=serializers.CharField(required=True,allow_blank=False,allow_null=False,write_only=True)

    # 只是在 注册成功之后，返回 只是获取数据
    token = serializers.CharField(read_only=True)

    class Meta:
        model = User
        fields = ['id','token','username','mobile','password','sms_code','allow','password2']
        # 注意： ModelSerializer 我们自己添加的字段，也是需要 添加到fields中
        # 如果不添加会报错

        extra_kwargs = {
            'id': {'read_only': True},
            'username': {
                'min_length': 5,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许5-20个字符的用户名',
                    'max_length': '仅允许5-20个字符的用户名',
                }
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    """
    用户名，手机号，密码，短信验证码，确认密码和是否同意协议

    1.数据类型的验证
    2.数据选项的验证
    3.单个字段验证
    4.多个字段验证
    """

    # 单个字段
    # 手机号，是否同意协议
    def validate_mobile(self,value):

        # 手机号的规则
        if not re.match(r'1[3-9]\d{9}',value):
            raise serializers.ValidationError('手机号格式不正确')

        return value

    def validate_allow(self,value):

        if value != 'true':
            raise serializers.ValidationError('您未同意协议')

        return value
    #多个字段
    # 密码和确认密码，短信验证码
    def validate(self, attrs):

        # 1. 密码和确认密码
        passwrod = attrs.get('password')
        passwrod2 = attrs.get('password2')
        if passwrod != passwrod2:
            raise serializers.ValidationError('密码不一致')

        #2.短信验证码
        #2.1 获取用户提交
        sms_code = attrs.get('sms_code')
        mobile = attrs.get('mobile')
        #2.2 获取redis的
        redis_conn=get_redis_connection('code')
        redis_sms_code=redis_conn.get('sms_%s'%mobile)
        if redis_sms_code is None:
            raise serializers.ValidationError('短信验证码已过期')
        #2.3 比对
        if redis_sms_code.decode() != sms_code:
            raise serializers.ValidationError('短信验证码错误')


        return attrs

    # 当父类的需求 不能满足我们的开发的时候 就是重写
    def create(self, validated_data):
        # 删除多余字段
        del validated_data['sms_code']
        del validated_data['allow']
        del validated_data['password2']

        # 实现数据保存
        # user = User.objects.create(**validated_data)

        # validated_data

        user = super().create(validated_data)

        # 修改密码
        user.set_password(validated_data.get('password'))
        # 调用模型的 保存方法
        user.save()

        # 在这里生成token
        from rest_framework_jwt.settings import api_settings

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token

        return user

class RegisterSmsCodeSerializer(serializers.Serializer):

    text=serializers.CharField(max_length=4,min_length=4,required=True,label='用户输入的图形验证码')

    image_code_id=serializers.UUIDField(required=True,label='uuid')



    def validate(self, attrs):
        # 1. 获取用户输入的
        text = attrs.get('text')

        image_code_id=attrs.get('image_code_id')
        # 2. 获取redis的
        redis_conn = get_redis_connection('code')

        redis_text = redis_conn.get('img_%s'%image_code_id)
        # redis的数据是有时效的
        if redis_text is None:
            raise serializers.ValidationError('图片验证码已过期')

        if redis_text.decode().lower() != text.lower():
            raise serializers.ValidationError('输入的不一致')

        return attrs

